package com.chenwenxuan.sync.console;

import java.util.Date;

import org.apache.commons.lang3.time.FastDateFormat;
import org.apache.log4j.Logger;

import com.chenwenxuan.sync.console.mail.MailQueue;
import com.chenwenxuan.sync.console.model.Task;
import com.chenwenxuan.sync.console.model.TaskArgs;
import com.chenwenxuan.sync.console.model.TaskRuntimeInfo;
import com.chenwenxuan.sync.console.service.TaskInvokerService;
import com.chenwenxuan.sync.console.task.ExecuteTask;
import com.chenwenxuan.sync.console.task.ExecuteTaskFactory;
import com.chenwenxuan.sync.utils.Commons;
import com.chenwenxuan.sync.utils.parser.TaskArgsParser;

public class TaskInvoker implements Runnable {

	private Logger logger = Logger.getLogger(TaskInvoker.class);
	
	private TaskInvokerService taskInvokerService;
	private MailQueue mailQueue;
	private ExecuteTask execTask;
	
	private Task task;

	private Date now;
	private Throwable t;
	
	public TaskInvoker() {
		now = new Date();
	}
	
	@Override
	public void run() {
		invoke();
	}
	
	public void invoke() {
		
		if ( !canRun() ) {
			logger.info("Running task " + task.getTaskId() + " " + task.getTaskName() + " skipped!");
			return;
		}
		
		execTask = ExecuteTaskFactory.create(task);
		if ( execTask == null ) {
			logger.error("Can not create task.");
			return;
		}
		
		TaskArgs taskArgs = taskInvokerService.getTaskArgs(task);
		
		TaskArgsParser argsParser = new TaskArgsParser(taskArgs, now);
		execTask.setContext(argsParser.getParamMap());
		execTask.setTask(task);
		execTask.setInvoker(this);
		execTask.setTaskService(taskInvokerService);
		
		//3 execute
		try {
			execTask.run();
		} catch (Throwable e) {
			t = e;
		}
		
		if ( t == null ) {
			t = execTask.collectTaskRuntimeInfo().getRuntimeExcepton();
		}
		
		updateTask();
		
		sendEmail();
		
	}
	
	private void updateTask() {
		
		if ( t == null ) {
			task.setLastExecute(FastDateFormat.getInstance(Commons.DATEFORMAT_TASK_LAST_EXECUTE).format(new Date()));
		}
		
		TaskRuntimeInfo runtimeInfo = execTask.collectTaskRuntimeInfo();
		
		taskInvokerService.updateTaskRuntimeInfo(task, runtimeInfo);
		
	}
	
	private void sendEmail() {
		mailQueue.addTaskExecuteResult(execTask.collectTaskRuntimeInfo());
	}
	
	protected boolean canRun() {
		//TODO
		return false;
	}
	
	public TaskInvokerService getTaskInvokerService() {
		return taskInvokerService;
	}

	public void setTaskInvokerService(TaskInvokerService taskInvokerService) {
		this.taskInvokerService = taskInvokerService;
	}

	public MailQueue getMailQueue() {
		return mailQueue;
	}

	public void setMailQueue(MailQueue mailQueue) {
		this.mailQueue = mailQueue;
	}

	public Date getNow() {
		return now;
	}

	public void setNow(Date now) {
		this.now = now;
	}
	
	public Task getTask() {
		return task;
	}

	public void setTask(Task task) {
		this.task = task;
	}

}
